package com.uplooking.util;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Iterator;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

/**
 * 异步加载网络图片，带内存缓存功能 此类默认加载最省内存的图片，使用加载头像图标之类的缩略图，如果需要加载更大的图片需要修改readBitmap（）方法；
 * 
 * @author zjingchuan
 * 
 */
public class AsyncImageLoader {
	/**
	 * 缓存，利用的SoftReference软引用，会在内存紧张时回收bitmap资源
	 */
	private final HashMap<String, SoftReference<Bitmap>> imageCache;

	/**
	 * 构造方法里实例化缓存
	 */
	public AsyncImageLoader() {
		imageCache = new HashMap<String, SoftReference<Bitmap>>();
	}

	/**
	 * 通过url加载图片资源，此方法会首先检查缓存里是否存在，如果存在则返回，如果没有下载过或已经被回收则重新下载；
	 * 
	 * @param imageUrl
	 *            图片的url
	 * @param imageCallback
	 *            回调接口，用以处理图片下载完成后的图片处理，需自己实现
	 * @return bitmap对象
	 */
	public Bitmap loadImage(final String imageUrl, final ImageCallback imageCallback) {
		Bitmap bitamp = null;
		bitamp = getBitmap(imageUrl);
		if (bitamp != null) {
			return bitamp;
		}

		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Bitmap) message.obj, imageUrl);
			}
		};
		// 开启一个线程去下载图片（此处是否应该用线程池来管理大量开启的临时线程？）
		new Thread(new Runnable() {
			@Override
			public void run() {
				Bitmap bitamp = null;
				bitamp = loadImageFromUrl(imageUrl);
				imageCache.put(imageUrl, new SoftReference<Bitmap>(bitamp));
				Message message = handler.obtainMessage(0, bitamp);
				handler.sendMessage(message);
			}
		}).start();

		return null;
	}

	/**
	 * 下载网络图片
	 * 
	 * @param url
	 * @return
	 */
	public static Bitmap loadImageFromUrl(String url) {
		try {
			Bitmap bitmap = readBitmap(url);
			return bitmap;
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			System.gc();
			return null;
			// Bitmap bitmap = BitmapFactory.decodeFile(url);
			// return bitmap;
		}
	}

	/**
	 * 判断缓存是否存在此图片的引用
	 * @param imageUrl
	 * @return
	 */



	public boolean getContainKey(String imageUrl) {
		if (TextUtils.isEmpty(imageUrl)) {
			return false;
		}
		return imageCache.containsKey(imageUrl);
	}

	/**
	 * 从缓存获取图片
	 * 
	 * @param key
	 * @return 存在则返回此bitmap，不存在则返回null；
	 */
	public Bitmap getBitmap(String key) {
		if (imageCache.containsKey(key)) {
			SoftReference<Bitmap> softReference = imageCache.get(key);
			return softReference.get();
		} else {
			return null;
		}
	}



	/**
	 * 以最省内存的方式读取图片
	 * 
	 * @param url
	 * @return
	 */
	public static Bitmap readBitmap(String url) {
		try {
			BitmapFactory.Options options = new BitmapFactory.Options();
			// 设置此值为true，调用decode方法获得图片的的时候会返回null，但可以通过options获得原始图片的尺寸
			options.inJustDecodeBounds = true;
			// 获取这个图片的宽和高
			BitmapFactory.decodeFile(url, options); // 此时返回bm为空
			// 原始图片大小
			int width = options.outWidth;
			int height = options.outHeight;
			options.inPreferredConfig = Bitmap.Config.RGB_565;
			options.inTempStorage = new byte[16 * 1024];
			options.inPurgeable = true;
			options.inInputShareable = true;
			int smallSampleSize = 1;
			int bigSampSize = 1;
			int max = width > height ? width : height;
			int pow = max / 1000;
			bigSampSize = (int) Math.pow(2, pow);
			smallSampleSize = bigSampSize * 2;
			options.inSampleSize = smallSampleSize;
			// 设置为false才可以获得一个bitmap对象
			options.inJustDecodeBounds = false;
			Bitmap bitmap = BitmapFactory.decodeFile(url, options);
			return bitmap;
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			System.gc();
			return null;
		}
	}

	/**
	 * 清空缓存
	 */
	public void removeAll() {
		Iterator iter = imageCache.entrySet().iterator();
		while (iter.hasNext()) {
			HashMap.Entry entry = (HashMap.Entry) iter.next();
			entry.getKey();
			Object obj = entry.getValue();
			SoftReference<Bitmap> bitmap = (SoftReference<Bitmap>) obj;
			if (bitmap != null && bitmap.get() != null) {
				bitmap.get().recycle();
				bitmap.get();
				bitmap = null;
			}
		}
		imageCache.clear();
		System.gc();
	}

	/**
	 * 图片下载完成后的回调接口，调用loadImage（）方法的时候需要自己实现此接口
	 * 
	 * @author zjingchuan
	 * 
	 */
	public interface ImageCallback {
		/**
		 * 图片下载完成后会调用此方法
		 * 
		 * @param imageDrawable
		 *            下载好的bitmap对象
		 * @param imageUrl
		 *            图片的原始url
		 */
		public void imageLoaded(Bitmap imageDrawable, String imageUrl);
	}
}